# -*- coding: utf-8 -*-
#!/usr/bin/env python

import os
import sys
import wsgiref.handlers
import webapp2
import json
import time
import logging
import csv
import glob
import base64
import urllib
import random
import string
import jinja2
import cgi

from datetime import datetime, timedelta
from operator import itemgetter
from google.appengine.api import memcache
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext import blobstore
from google.appengine.api import users
from google.appengine.ext.webapp import template
from google.appengine.api.logservice import logservice
from google.appengine.ext.deferred import defer
from google.appengine.runtime import DeadlineExceededError

import statistics as StatUtil
from utils import *
from events import *
from models import *
from game_handlers import *
from app_global import *
from services.gcm import *
from services.apns import *
from gaesessions import delete_expired_sessions

MAX_BATCH_SIZE = 100

def sowSeeds():
	logging.info('deleting Platforms, Mission, Season')
	ndb.delete_multi(Platform.query().fetch(keys_only=True))
	ndb.delete_multi(Mission.query().fetch(keys_only=True))
	ndb.delete_multi(Season.query().fetch(keys_only=True))
	logging.info('deleted Platforms, Mission, Season')
	
	logging.info('adding Platforms')
	Platform(parent=Platform.ancestorKey(),id=1,name="IOS",version=0,url=STORE_URL_IOS).put()
	Platform(parent=Platform.ancestorKey(),id=2,name="PlayStore",version=0,url=STORE_URL_PLAYSTORE).put()
	logging.info('added Platforms')
	
	logging.info('adding Mission')
	# 주간 미션의 가장 빠른 만료 날짜 설정
	missionExpireDate = datetime(2014,1,16,0,0,0) # 목요일 자정(한국시각)
	now = replace_timezone(datetime.now(), 'Asia/Seoul') # 현재 한국시각
	while missionExpireDate < now:
		missionExpireDate += timedelta(seconds=EXPIRE_INTERVAL_FOR_WEEKLY)
	mission = Mission(parent=Mission.ancestorKey(),id=1)
	mission.daily_missions=[1,2,3]
	mission.weekly_missions=[1,2,3]
	mission.weekly_expired_at = missionExpireDate
	mission.put()
	memcache.set("todayMission", mission)
	logging.info('added Mission')
	
	logging.info('adding Season')
	# 주간 시즌의 가장 빠른 만료 날짜 설정
	scoreExpireDate = replace_timezone(datetime(2014,1,2,3,0,0)) # seoul=목요일정오(+9)
	while scoreExpireDate < datetime.now():
		scoreExpireDate += timedelta(seconds=EXPIRE_INTERVAL_FOR_WEEKLY)
	season = Season(parent=Season.ancestorKey(),id=1)
	season.count=1
	season.expired_at=scoreExpireDate
	season.put()
	memcache.set("season", season)
	logging.info('added Season')
	
	logging.info('Re-initialization complete.')
	
def clearAll():
	logging.info('clearAll')
	classes = [DailyActiveUser, UpdatedPushToken, UserCharacter, UserFriendBout, UserInbox, UserRestricted, UserPurchase, ReservedPush, UserInvite, UserLog, Abuser, User,]
	for cls in classes:
		ndb.delete_multi(cls.query().fetch(keys_only=True))
	logging.info('clearAll is done')
	
class AdminHandler(webapp2.RequestHandler):
	@classmethod
	def logged_in(cls, handler_method):
		def auth_required(self, *args, **kwargs):
			if (users.get_current_user() or self.request.headers.get('X-AppEngine-Cron')):
				handler_method(self, *args, **kwargs)
			else:
				self.error(403)
		return auth_required
	
	def get(self):
		if not users.get_current_user() or not users.is_current_user_admin():
			self.redirect(users.create_login_url(self.request.uri))
			return
		
		logout_url = users.create_logout_url(self.request.uri)
		user_name = users.get_current_user().nickname()
		
		userCount = memcache.get("user_count")
		if not userCount:
			userCount = User.query().count()
			memcache.add("user_count", userCount, 20)
		
		template = jinja_environment.get_template('templates/admin_main.html')
		self.response.out.write(
			template.render(
				logout_url=logout_url,
				user_name=user_name,
				userCount=userCount,
			)
		)
		return

class PlatformsHandler(webapp2.RequestHandler):
	@AdminHandler.logged_in
	def get(self, platformId=None):
		logout_url = users.create_logout_url(self.request.uri)
		user_name = users.get_current_user().nickname()
		
		platforms = []
		for platform in Platform.query(ancestor=Platform.ancestorKey()).fetch():
			platforms.append(
				{
					"index":len(platforms),
					"id":platform.key.id(),
					"name":platform.name,
					"version":platform.version,
					"url":platform.url,
				}
			)
		
		platform = Platform.get_by_id(int(platformId), parent=Platform.ancestorKey()) if platformId else None
		
		template = jinja_environment.get_template('templates/admin_platforms.html')
		self.response.out.write(
			template.render(
				platforms=platforms,
				logout_url=logout_url,
				user_name=user_name,
				platform=platform,
			)
		)
		return
	
	@AdminHandler.logged_in
	def post(self):
		name = cgi.escape(self.request.get('name'))
		version = int(cgi.escape(self.request.get('version')))
		url = cgi.escape(self.request.get('url'))
		qry = Platform.query(ancestor=Platform.ancestorKey())
		platform = qry.filter(Platform.name==name).get()
		platform.version = version
		platform.url = url
		platform.put()
		
		time.sleep(2)
		memcache.set("%s:version" % PLATFORM_IOS, None)
		memcache.set("%s:version" % PLATFORM_PLAYSTORE, None)
	
		self.redirect('/admin/platforms')
		
		try:
			None
		except:
			self.error(400)
			self.response.out.write('Sorry, we had a problem processing the input-values.')
		
class AssetUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
	@AdminHandler.logged_in
	def post(self):
		try:
			# self.redirect('/download/asset/%s' % blob_info.key())
			name = cgi.escape(self.request.get('name'))
			platforms = self.request.get_all("platforms")
			version = int(cgi.escape(self.request.get('version')))
			upload_files = self.get_uploads('file')
			blob_info = upload_files[0] if len(upload_files)>0 else None
			
			for platform in platforms:
				Asset(parent=Asset.ancestorKey(),platform=int(platform), 
					version=version, name=name, 
					blob_key=(blob_info.key() if blob_info else None)
				).put()
				
			memcache.set("max_asset_version", None)
			
			time.sleep(2)
			self.redirect('/admin/assets')
		except:
			self.error(400)
			self.response.out.write('Sorry, we had a problem processing the input-values.')
		
class AssetsHandler(webapp2.RequestHandler):
	@AdminHandler.logged_in
	def get(self):
		logout_url = users.create_logout_url(self.request.uri)
		user_name = users.get_current_user().nickname()
		
		self.orders = [1 for i in range(6)]
		
		order = self.request.get('o')
		if order:
			tokens = order.split('.')
			self.orders[int(tokens[0])] = int(tokens[1])
		
		assets = []
		for asset in Asset.query(ancestor=Asset.ancestorKey()).fetch():
			object = {
				"id":asset.key.id(),
				"name":asset.name,
				"platform":Platform.get_by_id(asset.platform, parent=Platform.ancestorKey()).name,
				"version":asset.version,
				"url":None if asset.blob_key==None else ("%s/download/asset/%s" % (DOMAIN, asset.blob_key,)),
				"created_at":asset.created_at,
			}
			assets.append(object)
		
		assets = sorted(assets, key=itemgetter('created_at')) 
		for i in range(len(assets)):
			assets[i]["index"] = i
		
		upload_url = blobstore.create_upload_url('/admin/upload')
		template = jinja_environment.get_template('templates/admin_assets.html')
		self.response.out.write(
			template.render(
				assets=assets,
				upload_url=upload_url,
				logout_url=logout_url,
				user_name=user_name,
			)
		)
	
	@AdminHandler.logged_in
	def post(self):
		selected_assets = self.request.get_all("selected")
		
		assetKeys = []
		blobKeys = []
		
		for assetId in selected_assets:
			asset = Asset.get_by_id(int(assetId),parent=Asset.ancestorKey())
			blobKeys.append(asset.blob_key)
			assetKeys.append(asset.key)
		
		ndb.delete_multi(assetKeys)
		
		for blobKey in blobKeys:
			if Asset.query(Asset.blob_key==blobKey):
				blobKeys.remove(blobKey)
		
		blobstore.delete(blobKeys)
		
		if self.request.POST.has_key('_delete'):
			time.sleep(2)
			self.redirect('/admin/assets')
			return

class NoticesHandler(webapp2.RequestHandler):
	@AdminHandler.logged_in
	def get(self):
		logout_url = users.create_logout_url(self.request.uri)
		user_name = users.get_current_user().nickname()
		
		notices = []
		for notice in Notice.query(ancestor=Notice.ancestorKey()).fetch():
			object = {
				"index":len(notices),
				"id":notice.key.id(),
				"visible":notice.visible,
				"url":notice.url,
				"updated_at":notice.updated_at,
				"created_at":notice.created_at,
			}
			notices.append(object)
		
		template = jinja_environment.get_template('templates/admin_notices.html')
		self.response.out.write(
			template.render(
				notices=notices,
				logout_url=logout_url,
				user_name=user_name,
			)
		)
		return
	
	@AdminHandler.logged_in
	def post(self):
		if self.request.POST.has_key('_delete'):
			selected_platforms = self.request.get_all("selected")
		
			noticeKey = []
			
			for noticeId in selected_platforms:
				notice = Notice.get_by_id(int(noticeId),parent=Notice.ancestorKey())
				noticeKey.append(notice.key)
			
			ndb.delete_multi(noticeKey)
			
			memcache.set("Notice:notices", None)
			time.sleep(2)

			self.redirect('/admin/notices')
		else:
			visible=bool(self.request.get('visible'))
			url=cgi.escape(self.request.get('url'))

			Notice(parent=Notice.ancestorKey(),visible=visible,url=url).put()
			time.sleep(2)
			
			self.redirect('/admin/notices')
			return

class EventsHandler(webapp2.RequestHandler):
	@AdminHandler.logged_in
	def get(self, eventId=None):
		logout_url = users.create_logout_url(self.request.uri)
		user_name = users.get_current_user().nickname()
		
		events = []
		for event in EventConfig.query(ancestor=EventConfig.ancestorKey()).fetch():
			events.append(
				{
					"index":len(events),
					"id":event.key.id(),
					"title":event.title,
					"message":event.message,
					"visible":event.visible,
					"trigger":event.trigger,
					"start_at":replace_timezone(event.start_at,'Asia/Seoul').strftime('%Y-%m-%d %H:%M:%S') if event.start_at else None,
					"end_at":replace_timezone(event.end_at,'Asia/Seoul').strftime('%Y-%m-%d %H:%M:%S') if event.end_at else None,
					"count":event.count,
					"reward_type":event.reward_type,
					"reward_data":event.reward_data,
				}
			)
		
		event = EventConfig.get_by_id(int(eventId), parent=EventConfig.ancestorKey()) if eventId else None
		if event:
			event = {
				"id":event.key.id(),
				"title":event.title,
				"message":event.message,
				"visible":event.visible,
				"trigger":event.trigger,
				"start_date_at":replace_timezone(event.start_at,'Asia/Seoul').strftime('%Y-%m-%d') if event.start_at else None,
				"start_time_at":replace_timezone(event.start_at,'Asia/Seoul').strftime('%H:%M:%S') if event.start_at else None,
				"end_date_at":replace_timezone(event.end_at,'Asia/Seoul').strftime('%Y-%m-%d') if event.end_at else None,
				"end_time_at":replace_timezone(event.end_at,'Asia/Seoul').strftime('%H:%M:%S') if event.end_at else None,
				"count":event.count,
				"reward_type":event.reward_type,
				"reward_data":event.reward_data,
			}

		template = jinja_environment.get_template('templates/admin_events.html')
		self.response.out.write(
			template.render(
				event=event,
				events=events,
				logout_url=logout_url,
				user_name=user_name,
			)
		)
		return
	
	@AdminHandler.logged_in
	def post(self):
		if self.request.POST.has_key('_modify') or self.request.POST.has_key('_save'):
			visible = bool(self.request.get('visible'))
			title = cgi.escape(self.request.get('title'))
			message = cgi.escape(self.request.get('message'))
			start_date_at = cgi.escape(self.request.get('start_date_at')) if self.request.get('start_date_at') else None
			start_time_at = cgi.escape(self.request.get('start_time_at')) if self.request.get('start_time_at') else None
			end_date_at = cgi.escape(self.request.get('end_date_at')) if self.request.get('start_time_at') else None
			end_time_at = cgi.escape(self.request.get('end_time_at')) if self.request.get('end_time_at') else None
			count = int(self.request.get('count'))
			trigger = int(self.request.get('trigger'))
			reward_type = int(self.request.get('reward_type'))
			reward_data = int(self.request.get('reward_data'))
			
			config = None
			if self.request.POST.has_key('_modify'):
				eventId = int(self.request.get('eventId'))
				config = EventConfig.get_by_id(eventId, parent=EventConfig.ancestorKey())
			else:
				maxId = 0
				for c in EventConfig.query(ancestor=EventConfig.ancestorKey()):
					maxId = max(maxId, c.key.id())
				maxId += 1
				config = EventConfig(id=maxId, parent=EventConfig.ancestorKey())
			config.visible = visible
			config.title = title
			config.message = message
			config.start_at = replace_timezone(datetime.strptime(start_date_at+start_time_at, "%Y-%m-%d%H:%M:%S")) if start_date_at and start_time_at else None
			config.end_at = replace_timezone(datetime.strptime(end_date_at+end_time_at, "%Y-%m-%d%H:%M:%S")) if end_date_at and end_time_at else None
			config.count = count
			config.trigger = trigger
			config.reward_type = reward_type
			config.reward_data = reward_data
			config.put()
			time.sleep(2)
			self.redirect('/admin/events')
			return
		
		time.sleep(2)
		self.redirect('/admin/')

class PushesHandler(webapp2.RequestHandler):
	@AdminHandler.logged_in
	def get(self):
		logout_url = users.create_logout_url(self.request.uri)
		user_name = users.get_current_user().nickname()
		
		if user_name.startswith("brgames.cj.cs"):
			self.redirect('/cs/')
			return
		
		pushes = []
		index = 0
		for push in ReservedPush.query(ancestor=ReservedPush.ancestorKey()).order(-ReservedPush.created_at).fetch(8):
			step = u"제한 시간 초과"
			if push.step==0:
				step = u"완료"
			elif push.step==1:
				step = u"예약"
			elif push.step==2:
				step = u"보내는 중"
			elif push.step>=3:
				step = u"이어보내는 중{0}, user({1})".format(push.step-3, push.count)
				
			pushes.append(
				{
					"index":index,
					"id":push.key.id(),
					"step":step,
					"platform_name":Platform.get_by_id(push.platform_id).name,
					"application_version":push.application_version,
					"asset_version":push.asset_version,
					"user_ids":",".join(str(i) for i in push.user_ids),
					"reserved_at":replace_timezone(push.reserved_at,'Asia/Seoul').strftime('%Y-%m-%d %H:%M:%S') if push.reserved_at else None,
					"deadline_at":replace_timezone(push.deadline_at,'Asia/Seoul').strftime('%Y-%m-%d %H:%M:%S') if push.deadline_at else None,
					"title":push.title,
					"message":push.message,
					"badge":push.badge,
					"created_at":replace_timezone(push.created_at,'Asia/Seoul').strftime('%Y-%m-%d %H:%M:%S'),
				}
			)
			index += 1
		
		template = jinja_environment.get_template('templates/admin_pushes.html')
		self.response.out.write(
			template.render(
				pushes=pushes,
				logout_url=logout_url,
				user_name=user_name,
			)
		)
		return
	
	@AdminHandler.logged_in
	def post(self):
		if self.request.POST.has_key('_save'):
			platforms = self.request.get_all("platforms")
			appVersion = int(cgi.escape(self.request.get('app_version')))
			assetVersion = int(cgi.escape(self.request.get('asset_version')))
			reserved_date_at = cgi.escape(self.request.get('reserved_date_at')) if self.request.get('reserved_date_at') else None
			reserved_time_at = cgi.escape(self.request.get('reserved_time_at')) if self.request.get('reserved_time_at') else None
			reserved_at = replace_timezone(datetime.strptime(reserved_date_at + reserved_time_at, "%Y-%m-%d%H:%M:%S")) if reserved_date_at and reserved_time_at else None
			deadline_date_at = cgi.escape(self.request.get('deadline_date_at')) if self.request.get('deadline_date_at') else None
			deadline_time_at = cgi.escape(self.request.get('deadline_time_at')) if self.request.get('deadline_time_at') else None
			deadline_at = replace_timezone(datetime.strptime(deadline_date_at + deadline_time_at, "%Y-%m-%d%H:%M:%S")) if deadline_date_at and deadline_time_at else None
			title = cgi.escape(self.request.get('title'))
			message = cgi.escape(self.request.get('message'))
		
			for platform in platforms:
				push = ReservedPush(platform_id=int(platform))
				push.application_version = appVersion
				push.asset_version = assetVersion
				push.reserved_at = reserved_at
				push.deadline_at = deadline_at
				push.title = title
				push.message = message
				
				push.put()
		
			time.sleep(2)
			self.redirect('/admin/pushes')
			try:
				None
			except:
				self.error(400)
				self.response.out.write('Sorry, we had a problem processing the input-values.')
				
		elif self.request.POST.has_key('_send'):
			title = cgi.escape(self.request.get('title'))
			message = cgi.escape(self.request.get("message"))
			userIds = self.request.get("user_ids")
			if userIds and userIds.endswith(','):
				userIds = userIds[0:len(userIds) - 1]
			
			userIds = [int(i) for i in userIds.split(',')] if userIds else []
			
			iosUsers = []
			androidUsers = []
			for userId in userIds :
				user = User.get_by_id(userId)
				if not user :
					continue
				if user.platform_id == 1:
					iosUsers.append(PushUser(user, user.platform_id))
				else:
					androidUsers.append(PushUser(user, user.platform_id))

			if len(iosUsers) > 0:
				sendMulticastApnsMessage(iosUsers, convertToApnsMessage({
					"request": {
						"message":u"{0}\n{1}".format(title, message),
						"custom": {}
					}
				}))
			if len(androidUsers) > 0:
				sendMulticastGcmMessage(androidUsers, convertToGcmMessage({
					"request": {
						"message":message,
						"title":title,
						"custom": {}
					}
				}))
		
			self.redirect('/admin/pushes')

class ManageHandler(webapp2.RequestHandler):
	@AdminHandler.logged_in
	def post(self):
		jsonParams = json.loads(self.request.body)

		try:
			result = {"result":0}
			
			logging.info("action=%s" % jsonParams['action'])
			
			if jsonParams['action'] == 'seeds':
				sowSeeds()
				#defer(sowSeeds)
			elif jsonParams['action'] == 'clearAll':
				defer(clearAll)
			elif jsonParams['action'] == 'maxCharacterPoint':
				user = User.get_by_id(jsonParams['userId'])
				if user:
					c = user.getCharacter(user.character_id)
					c.point = 100
					c.put()
				else:
					result["result"] = "not found"
			elif jsonParams['action'] == 'test':
				user = User.get_by_id(jsonParams['userId'])
				result["result"] = user.event_record

			self.response.headers['Content-Type'] = 'application/json;charset=utf-8'
			self.response.write(json.dumps(result))
		except:
			logging.info("Unexpected error: %s" % sys.exc_info()[0])
			self.error(400) # Bad Request

class CleanupSessionsHandler(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		while not delete_expired_sessions():
			pass
		self.response.out.write('0')

class WeeklyScoreExpireHandler(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		Season.incr()
		self.response.out.write('0')

# kind가 중복되지 않도록, 3개의 임의의 미션을 구한다.
def distinctMissionSamples(missions, count):
	results = None
	while results is None:
		results = random.sample(missions, count)
		kinds = [m["kind"] for m in results]
		while len(kinds)>0:
			if kinds.__contains__(kinds.pop()):
				results = None
				break
	return results
	
class WeeklyMissionExpireHandler(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		mission = Mission.query().get()
		w3 = distinctMissionSamples(getStorageData("weekly-missions"), 3)
		mission.weekly_missions=[m["id"] for m in w3]
		mission.weekly_season += 1
		mission.weekly_expired_at = mission.weekly_expired_at + timedelta(days=7)
		mission.put()
		memcache.set("todayMission", mission)
		self.response.out.write('0')
	
class DailyMissionExpireHandler(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		mission = Mission.query().get()
		d3 = distinctMissionSamples(getStorageData("daily-missions"), 3)
		mission.daily_missions=[m["id"] for m in d3]
		mission.daily_season += 1
		mission.put()
		memcache.set("todayMission", mission)
		self.response.write("OK\n")

###############################################################################
## Push

class PushUser(object):
	def __init__(self, user, platform_id):
		super(PushUser, self).__init__()
		self.userId = user.key.id()
		self.platform = platform_id
		self.pushToken = user.push_token

def convertToGcmMessage(message):
	gcmmessage = {}
	gcmmessage["message"] = {}
	
	if 'android_collapse_key' in message["request"]:
		gcmmessage["collapse_key"] = message["request"]["android_collapse_key"]
	
	if 'message' in message["request"]:
		gcmmessage["message"] = message["request"]["message"]
	if 'title' in message["request"]:
		gcmmessage["title"] = message["request"]["title"]
		
	return gcmmessage

def convertToApnsMessage(message):
	apnsmessage = {}
	apnsmessage["message"] = {}
	apnsmessage["sound"] = "default"
	apnsmessage["badge"] = -1
	apnsmessage["alert"] = None
	apnsmessage["custom"] = None
	
	if 'ios_sound' in message["request"]:
		message["sound"] = message["request"]["ios_sound"]
	
	if 'custom' in message["request"]:
		apnsmessage["custom"] = message["request"]["custom"]
	
	if 'ios_badge' in message["request"]:
		apnsmessage["badge"] = message["request"]["ios_badge"]
	
	if 'ios_message' in message["request"] and 'ios_button_text' in message["request"]:
		apnsmessage["alert"] = PayloadAlert(message["request"]["ios_message"], action_loc_key=message["request"]["ios_button_text"])
	else:
		if 'ios_message' in message["request"]:
			apnsmessage["alert"] = message["request"]["ios_message"]
		elif 'message' in message["request"]:
			apnsmessage["alert"] = message["request"]["message"]
	
	return apnsmessage

def sendMulticastGcmMessage(users, gcmmessage):
	gcm = GCM(GCM_KEY)

	# JSON request
	userDict = {}
	for u in users:
		userDict[u.pushToken] = u.userId
		
	tokens = userDict.keys()
	
	index = 0
	while True:
		t = tokens[index:index+500]
		if len(t)==0:
			break
		index += 500
		
		response = gcm.json_request(registration_ids=t, data=gcmmessage)
		if 'errors' in response:
			for error, reg_ids in response['errors'].items():
				if error is 'NotRegistered':
					for reg_id in reg_ids:
						user = User.get_by_id(userDict[reg_id])
						user.push_token = None
						user.put()
		if 'canonical' in response:
			for reg_id, canonical_id in response['canonical'].items():
				# Repace reg_id with canonical_id in your database
				user = User.get_by_id(userDict[reg_id])
				user.push_token = canonical_id
				user.put()

def sendMulticastApnsMessage(users, apnsmessage):
	apns = None
	if APP_DEBUG:
		apns = APNs(use_sandbox=True, cert_file="files/apns_development.pem", key_file="files/apns_key")
	else:
		apns = APNs(use_sandbox=False, cert_file="files/apns_production.pem", key_file="files/apns_key")

	payload = Payload(alert=apnsmessage["alert"], sound=apnsmessage["sound"], custom=apnsmessage["custom"], badge=apnsmessage["badge"])
	apns.gateway_server.send_notifications([u.pushToken for u in users], payload)

	for (token_hex, fail_time) in apns.feedback_server.items():
		logging.info('token_hex: %s, fail_time: %s' % (token_hex, fail_time,))
		break
		
class SendPush(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		title = cgi.escape(self.request.get("title"))
		message = cgi.escape(self.request.get("message"))
		userId = int(self.request.get("userId"))
		
		user = User.get_by_id(userId)
		if not user or not user.push_token:
			self.response.write("Not exists")
			return
		
		users = [ PushUser(user, user.platform_id) ]
		
		if user.platform_id == 1: #iOS
			sendMulticastApnsMessage(users, convertToApnsMessage(json.loads(message)))
		elif user.platform_id == 2: #Android
			sendMulticastGcmMessage(users, convertToGcmMessage(json.loads(message)))

		self.response.write("OK")

###############################################################################
## Statistics

class MidnightHandler(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		while True:
			daus = DailyActiveUser.query().fetch(500, keys_only=True)
			if len(daus)==0:
				break
			ndb.delete_multi(daus)
		self.response.out.write('OK')

class StatisticsHandler(AdminHandler):
	@AdminHandler.logged_in
	def get(self):
		# Accrue statistics
		now = datetime.now()		
		
		stamp = int(replace_timezone(now, 'Asia/Seoul').strftime('%Y%m%d%H'))
		stampUTC = int((now-timedelta(hours=1)).strftime('%Y%m%d%H'))
		
		while True:
			try:
				if StatUtil.accrueStatistics(stamp, stampUTC):
					break
			except DeadlineExceededError as de:
				logging.info("statistics error!")
		
		stamp = int(replace_timezone(now, 'Asia/Seoul').strftime('%Y%m%d'))
		while True:
			try:
				if StatUtil.ratioStatistics(stamp):
					break
			except DeadlineExceededError as de:
				logging.info("ratioStatistics error!")
		
		self.response.out.write('OK')